using Microsoft.Win32;
using NEM.Networking_Classes;
using NEM.Windows_Forms;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Management;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Xml;
using System.Xml.Serialization;
using System.Security.Principal;

namespace NEM
{
    public partial class frmMenuScreen : Form
    {

        #region Private Variables / Constants
        private List<NetworkProfileClass> _ListOfProfiles = null;
        #endregion

        #region Constructors
        public frmMenuScreen()
        {
            InitializeComponent();

            this.ShowInTaskbar = false;            
            this.TopMost = true;

            //Check if user has the Roll of Administrator.
            if (!IsUserAdministrator())
            {
                //Warning message
                MessageBox.Show("Please not that the application needs to read and write to Windows Registry, This could require Administrator right.","No Administrator Rights.");
            }

            #region Load Network Cards
            //Load Network Cards
            NetworkConnections lvConnections = new NetworkConnections();
            lvConnections.GetConnectionsUpdate();
            NetworkCardConverter._NetworkCards = lvConnections.Connections;
            #endregion End of Load Network Cards

            //Load all the Network Profiles.
            LoadNetworkProfiles();

            #region Load Application Settings
            if (ConfigurationFileFound() == true)
            {
                Globals.LoadApplicationSettings(SaveType.File);
            }
            else
            {
                Globals.LoadApplicationSettings(SaveType.Registry);
            }
            #endregion End of Load Application Settings

            #region Show or Hide Application
            //Set Form State from Settings.
            if (Globals.ApplicationSettings.StartHidden)
            {
                this.WindowState = FormWindowState.Minimized;
            }
            else
            {
                this.WindowState = FormWindowState.Normal;
            }
            #endregion End of Show or Hide Application

            #region Windows Startup
            try
            {
                RegisterInStartup(Globals.ApplicationSettings.AutoStart);
            }
            catch (Exception)
            {
            }
            #endregion End of Windows Startup

        }


        #endregion

        #region Properties

        #endregion

        #region Methods

   
        public bool IsUserAdministrator()
        {             
            bool lvResult;
            try
            {
                WindowsIdentity lvUser = WindowsIdentity.GetCurrent();
                WindowsPrincipal lvPrincipal = new WindowsPrincipal(lvUser);
                lvResult = lvPrincipal.IsInRole(WindowsBuiltInRole.Administrator);
            }
            catch (UnauthorizedAccessException ex)
            {
                lvResult = false;
            }
            catch (Exception ex)
            {
                lvResult = false;
            }
            return lvResult;
        }

        private bool ConfigurationFileFound()
        {
            bool lvResult = false;

            //Check if there are Config Files in the Application Startup Path.
            Globals.ApplicationFolderPath = Path.GetDirectoryName(Application.ExecutablePath);
            string lvFolderPath = Path.GetDirectoryName(Application.ExecutablePath);
            if (!lvFolderPath.EndsWith("\\"))
                lvFolderPath += "\\";

            if (File.Exists(lvFolderPath + "Application Settings"))
            {
                lvResult = true;
            }
            else
            {
                lvResult = false;
            }


            return lvResult;
        }

        /// <summary>
        /// This Function will Reload the GUI Items and assign events.
        /// </summary>
        private void ReloadGUI()
        {
            if (_ListOfProfiles != null)
            {
                lbxNetworkProfiles.Items.Clear();
                lbxNetworkProfiles.Items.AddRange(_ListOfProfiles.ToArray());

                //Populate menuStrip drop down items.
                (contextMenuStrip1.Items[1] as ToolStripMenuItem).DropDownItems.Clear();
                foreach (NetworkProfileClass item in lbxNetworkProfiles.Items)
                {
                    (contextMenuStrip1.Items[1] as ToolStripMenuItem).DropDownItems.Add(item.ProfileName);
                    (contextMenuStrip1.Items[1] as ToolStripMenuItem).DropDownItems[(contextMenuStrip1.Items[1] as ToolStripMenuItem).DropDownItems.Count - 1].Tag = item.ProxyInformation.ID;
                    (contextMenuStrip1.Items[1] as ToolStripMenuItem).DropDownItems[(contextMenuStrip1.Items[1] as ToolStripMenuItem).DropDownItems.Count - 1].Click += frmMenuScreen_Click;
                }
            }
        }

        /// <summary>
        /// Loads the settings from the Registry.
        /// </summary>
        /// <returns>If it was able to load settings form the registry.</returns>
        private bool LoadNetworkProfiles()
        {
            bool lvResult = true;
            _ListOfProfiles = new List<NetworkProfileClass>();

            Globals.Logger.LogMessage(string.Format("*****Enter Function***** \nFunction: [{0}] \n Parameters: [{1}]", "LoadSettings", ""));

            if (Globals.ApplicationSettings.MainSaveType == SaveType.Registry)
            {
                #region Load from registry
                try
                {
                    Globals.Logger.LogMessage("Try to Open Registry Key Holding Proxy Info");

                    RegistryKey lvRegKey = Registry.CurrentUser.OpenSubKey(@"Software\\Tainted Mentality\\Network Environment Manager", true);

                    if (lvRegKey == null)
                    {
                        lvResult = false;
                    }
                    else
                    {
                        string lvKeyValue = lvRegKey.GetValue("Network Profiles").ToString();
                        _ListOfProfiles = lvKeyValue.FromJson<List<NetworkProfileClass>>();
                    }
                }
                catch (Exception ex)
                {
                    lvResult = false;
                }
                #endregion End Load from registry
            }
            else
            {
                //Load from File.
                lvResult = false;
            }

            if (lvResult)
            {
                ReloadGUI();
            }

            return lvResult;
        }


        /// <summary>
        /// Saves the settings to the Registry.
        /// </summary>
        /// <returns>if it was able to Save to registry</returns>
        private bool SaveNetworkProfiles()
        {
            bool lvResult = true;

            if (Globals.ApplicationSettings.MainSaveType == SaveType.Registry)
            {
                #region Save to Registry
                try
                {
                    RegistryKey lvRegKey = Registry.CurrentUser.CreateSubKey(@"Software\\Tainted Mentality\\Network Environment Manager");
                    lvRegKey.SetValue("Network Profiles", _ListOfProfiles.ToJson(), RegistryValueKind.ExpandString);
                }
                catch (Exception ex)
                {
                    MessageBox.Show("Error : " + ex.Message);
                    lvResult = false;
                }
                #endregion end Save to Registry
            }
            else
            {
                #region Save to File

                try
                {
                    StreamWriter lvStreamWriter = new StreamWriter(Globals.ApplicationFolderPath + "Network Profiles", true);

                    lvStreamWriter.WriteLine(_ListOfProfiles.ToJson());
                    lvStreamWriter.Flush();

                    lvStreamWriter.Close();

                    lvResult = true;
                }
                catch (Exception ex)
                {
                    lvResult = false;
                }

                #endregion End Save to File.
            }


            if (lvResult)
            {
                ReloadGUI();
            }

            return lvResult;
        }


        private bool RegisterInStartup(bool isChecked)
        {

            bool lvResult = true;

            try
            {
                RegistryKey registryKey = Registry.CurrentUser.OpenSubKey
                            ("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true);
                if (isChecked)
                {
                    registryKey.SetValue("Network Environment Manager", Application.ExecutablePath);
                }
                else
                {
                    registryKey.DeleteValue("Network Environment Manager");
                }
            }
            catch (Exception)
            {
                lvResult = false;
                throw;
            }

            return lvResult;
        }
        #endregion

        #region Events
        private void btnNew_Click(object sender, EventArgs e)
        {
            NetworkProfileClass lvNewProfile = new NetworkProfileClass();            
            lvNewProfile.ProxyInformation.NewProxyInfo = true;

            propGridProxySettings.SelectedObject = lvNewProfile;
        }

        private void btnSave_Click(object sender, EventArgs e)
        {
            bool lvResult = true;
            NetworkProfileClass lvTempProfile = null;
            string lvValidationErrors = string.Empty;

            if (propGridProxySettings.SelectedObject != null)
            {

                try
                {
                    lvTempProfile = ((NetworkProfileClass)propGridProxySettings.SelectedObject);
                }
                catch (Exception ex)
                {
                    lvResult = false;
                    MessageBox.Show("Error : " + ex.Message);
                }

                if (lvResult)
                {


                    if (!lvTempProfile.Validate(out lvValidationErrors))
                    {
                        lvResult = false;
                        MessageBox.Show(lvValidationErrors,"Validation Problems");
                    }

                }



                if (lvResult)
                {

                        //Add Profile
                        if (lvTempProfile.ProxyInformation.NewProxyInfo)
                        {
                            //Add new Proxy Settings
                            lvTempProfile.ProxyInformation.NewProxyInfo = false;
                            _ListOfProfiles.Add(lvTempProfile);
                        }
                        else
                        {
                            //Update Current Settings.
                            _ListOfProfiles.Remove(_ListOfProfiles.Where(proxy => proxy.ProxyInformation.ID == lvTempProfile.ProxyInformation.ID).FirstOrDefault());
                            lvTempProfile.ProxyInformation.NewProxyInfo = false;
                            _ListOfProfiles.Add(lvTempProfile);
                        }
                    
                }
            }
            else
            {
                lvResult = false;
            }

            if (lvResult)
            {
                lvResult = SaveNetworkProfiles();
            }


            if(lvResult)
                MessageBox.Show("Network profile has been saved.","Saved Network Profile.");
            else
                MessageBox.Show("There was an error saving Network Profile.", "Error Saving Network Profile.");
        }

        void frmMenuScreen_Click(object sender, EventArgs e)
        {
            //Update to selected Proxy
            NetworkProfileClass lvSelectedProfile = _ListOfProfiles.Where(profile => profile.ProxyInformation.ID.ToString() == ((ToolStripItem)sender).Tag.ToString()).FirstOrDefault();
            lvSelectedProfile.AcitvateProfile();

            if (lvSelectedProfile.AllowNotification)
            {
                notifyIcon1.BalloonTipTitle = "Network Environment Manager - Update";
                notifyIcon1.BalloonTipText = string.Format("Profile Loaded: {0} \nDescription: {1}",lvSelectedProfile.ProfileName,lvSelectedProfile.ProfileDescription);

                if (lvSelectedProfile.Variable != string.Empty)
                {
                    notifyIcon1.BalloonTipText += "{0}Profile Notes:{1}{2}"
                        .FormatString(Environment.NewLine, Environment.NewLine, lvSelectedProfile.Variable);
                }

                notifyIcon1.ShowBalloonTip(lvSelectedProfile.NotificationShowTime);
            }
        }

        private void lbxProxys_SelectedIndexChanged(object sender, EventArgs e)
        {
            propGridProxySettings.SelectedObject = lbxNetworkProfiles.SelectedItem;
        }

        private void exitApplicationToolStripMenuItem_Click(object sender, EventArgs e)
        {
            Application.Exit();
        }

        private void button1_Click(object sender, EventArgs e)
        {
        }

        private void applicationSettingsToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            frmApplicationSettings frmSettingsForm = new frmApplicationSettings();
            frmSettingsForm.ShowDialog();
        }

        private void importFormFileToolStripMenuItem_Click(object sender, EventArgs e)
        {

        }

        private void ShowFormToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
        }

        private void btnActivate_Click(object sender, EventArgs e)
        {
            bool lvResult = true;
            if (lbxNetworkProfiles.SelectedItem != null)
            {
                NetworkProfileClass lvSelectedProfile = null;

                if (lbxNetworkProfiles.SelectedItem != null)
                {

                    try
                    {
                        lvSelectedProfile = ((NetworkProfileClass)lbxNetworkProfiles.SelectedItem);
                        lvSelectedProfile.AcitvateProfile();
                    }
                    catch (Exception)
                    {
                        lvResult = false;
                        throw;
                    }
                }

                if (lvSelectedProfile.AllowNotification && lvResult)
                {
                    notifyIcon1.BalloonTipTitle = "Network Environment Manager - Update";
                    notifyIcon1.BalloonTipText = string.Format("Profile Loaded: {0} \nDescription: {1}", lvSelectedProfile.ProfileName, lvSelectedProfile.ProfileDescription);

                    if (lvSelectedProfile.Variable != string.Empty)
                    {
                        notifyIcon1.BalloonTipText += "{0}Profile Notes:{1}{2}"
                            .FormatString(Environment.NewLine, Environment.NewLine, lvSelectedProfile.Variable);
                    }

                    notifyIcon1.ShowBalloonTip(lvSelectedProfile.NotificationShowTime);
                }
            }
        }

        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            this.WindowState = FormWindowState.Normal;
        }
        #endregion

        #region Overrides
        public override string ToString()
        {
            return "Manage Proxy's Screen";
        }

        
        #endregion

        private void frmMenuScreen_MinimumSizeChanged(object sender, EventArgs e)
        {

        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            NetworkFunctions.TestProxyCredentials("http://www.google.com");
        }

    }
}
